Network Stack

Home

Services running on PCT 108 (network, 192.168.2.82) — the Docker Swarm manager node.


Service URLs

Service URL Internal
Traefik dashboard traefik.carr-family.org 192.168.2.82:443
Portainer portainer.carr-family.org 192.168.2.82:9443 (HTTPS)
Homarr homepage.carr-family.org 192.168.2.82:7575
Authentik auth.carr-family.org
Guacamole guac.carr-family.org 192.168.2.82:8080
CloudBeaver db.carr-family.org 192.168.2.82:8978
Dozzle dozzle.carr-family.org — (global, all nodes)

Authentik (stack: authentik, compose 23)

SSO at auth.carr-family.org. Image: ghcr.io/goauthentik/server:2026.2.

Services: server, worker, proxy outpost, postgres:16-alpine (host port 5433), redis:7-alpine.

Proxy outpost (ghcr.io/goauthentik/proxy:2026.2) — handles Traefik ForwardAuth requests. Connects to authentik and traefik-public networks. ForwardAuth address: http://authentik_authentik-proxy:9000/outpost.goauthentik.io/auth/traefik.

The proxy outpost also has its own Traefik router (authentik-outpost) that catches all *.carr-family.org requests with path /outpost.goauthentik.io/ (priority 15) so auth callbacks work after login.

Env file: /root/authentik.env on PCT 108 (chmod 600). Required vars: AUTHENTIK_SECRET_KEY, PG_USER, PG_PASS, PG_DB.

Redeploy:

pct exec 108 -- bash -c "set -a && source /root/authentik.env && set +a && docker stack deploy -c /mnt/tank/appdata/portainer/compose/23/docker-compose.yml authentik"

Trusted IP bypass: LAN 192.168.2.0/24, Tailscale 100.64.0.0/10, 205.194.16.9/32 (friend's house). Edit in Authentik Admin → Policy Engine → Policies → Trusted IP Bypass.

IP bypass mechanism: Expression Policy Trusted IP Bypass is bound (un-negated) to the Identification and Password stages of default-authentication-flow. Returns False for trusted CIDRs → stages skipped → auto-authenticated.

Note (2026-06-12): authentik middleware removed from all routes.yml routers — all static routes are now unprotected. Services with authentik in their compose deploy.labels still have it but the middleware definition is gone. To re-enable for a service, add authentik@file middleware definition back to routes.yml first.

Note (2026-05-29): Secret key and PG_PASS were regenerated after Portainer lost env vars. Sessions invalidated; DB intact.


Homarr (stack: documents-homarr, compose 22)

Dashboard at homepage.carr-family.org. Image: ghcr.io/homarr-labs/homarr:latest. Pinned to manager node.

  • Port: 3001 (published) → 7575 (internal nginx); Traefik label also targets 7575 (internal port is 7575, not 3000)
  • Appdata: /mnt/tank/appdata/homarr/ on PCT 108 rootfs (LVM, not ZFS)
  • DB: /mnt/tank/appdata/homarr/db/db.sqlite (SQLite)
  • Encryption key: SECRET_ENCRYPTION_KEY in compose (AES-256-CBC)
  • Population script: /root/populate-homarr.js on Proxmox host (regenerates all apps/sections/integrations from scratch)

After any re-populate, restore board permissions:

pct exec 108 -- sqlite3 /mnt/tank/appdata/homarr/db/db.sqlite "
INSERT OR IGNORE INTO boardUserPermission VALUES ('a2tzcbvgfkkt16aamvuwa6rs','bskmlbq5oayy4845ekbomk9y','full');
INSERT OR IGNORE INTO boardGroupPermission VALUES ('a2tzcbvgfkkt16aamvuwa6rs','nw94xpf6j307ceruir2b82x9','full');"

To edit DB safely: scale to 0, edit, scale to 1.

Integrations configured: Sonarr, Radarr, Prowlarr, Jellyseerr (all apiKey).

Manual setup required: Jellyfin (username+password, not API key), qBittorrent.

Do not add: immich and paperlessNgx integration kinds crash the integrations page in this Homarr version.


Guacamole (stack: network-guacamole, compose 6)

Remote desktop gateway at guac.carr-family.org. guacamole v1.6.0 + guacd + postgresql:15 (host port 5434). All services 1/1.


CloudBeaver (stack: network-cloudbeaver, compose 31)

DB viewer at db.carr-family.org (lan-only). Pinned to network node. Workspace: /mnt/tank/appdata/cloudbeaver/workspace.

DB Connections:

Name Host Port User Password DB
authentik 192.168.2.82 5433 authentik (see /root/authentik.env on PCT 108) authentik
guacamole 192.168.2.82 5434 guacamole 32Ab0321!! guacamole
nextcloud 192.168.2.105 5432 nextcloud 32Ab0321!! nextcloud
paperless 192.168.2.105 5433 paperless eWJarhDasRNBu0LfBwuI6VPOXwnRCUy paperless
linkwarden 192.168.2.105 5434 postgres 32Ab0321!! postgres
immich 192.168.2.105 5435 immich T5dBbAvgHWceH7jhsxjism4b2Cre9NA immich
litellm 192.168.2.83 5433 litellm litellm litellm

Postgres ports are exposed host-mode on each node's LAN IP. Redeploy the DB stack after adding new port mappings.


Watchtower (stack: watchtower)

Automatic image updates daily at 04:00 AM (0 0 4 * * * — cron6 format, seconds first).

  • Mode: Global (one instance per node — covers Swarm services and standalone containers on all nodes)
  • Config: WATCHTOWER_CLEANUP=true, WATCHTOWER_ROLLING_RESTART=true, DOCKER_API_VERSION=1.40
  • Compose: /mnt/tank/appdata/watchtower/docker-compose.yml
  • TZ: America/New_York
  • Notifications: Disabled (removed 2026-06-12 — was spamming emails). The smtp-relay sidecar (boky/postfix) remains in the compose file but is unused.

DOCKER_API_VERSION=1.40 is required — Watchtower defaults to 1.25 which Docker 29.x rejects (minimum accepted is 1.40).

Excluding containers — containers with network_mode: "service:..." or depends_on are incompatible with WATCHTOWER_ROLLING_RESTART=true. Watchtower exits with code 1 on startup if it finds one. Exclude with:

labels:
  - "com.centurylinklabs.watchtower.enable=false"

Currently excluded (update manually):

  • gluetun-proton and qbittorrent-vpn — compose at /root/stacks/bittorrent-vpn/docker-compose.yml on PCT 101; qbittorrent-vpn uses network_mode: "service:gluetun"

Dozzle (stack: dozzel, compose 25)

Live container log viewer at dozzle.carr-family.org. Global mode — one instance per worker node (does not run on PCT 108 manager).


Portainer (stack: network)

Swarm UI at portainer.carr-family.org (port 9443 HTTPS). Image: portainer/portainer-ce:latest.

  • Stack compose files: /mnt/tank/appdata/portainer/compose/<id>/docker-compose.yml
  • Internal DB: network_portainer_data Docker volume on PCT 108 rootfs
  • Env var gotcha: Portainer stores stack env vars in its internal DB — there are no .env files on disk. When redeploying via CLI, always export vars manually in the shell first.